home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PACKET / CBBS60SO.ZIP / MBMAIL.C < prev    next >
Text File  |  1989-02-17  |  40KB  |  1,780 lines

  1. /*
  2.  *  MBMAIL.C - 2/04/89 The message file stuff, except for forwarding.
  3.  */
  4.  
  5. #include "mb.h"
  6.  
  7. #define btmax 112   /* Max text in beacon line */
  8.  
  9. char  orgmsg[6], orgbbs[7], orgtime[5], orgdate[7];
  10.  
  11. char  *mbfile, *mbbfile, *msgdir, *bidfile;
  12.  
  13. char  *ufwd;  /* Calls with unread msgs, for BT */
  14. char  *bfwd;  /* Calls with unread msgs, for forwarding */
  15.  
  16. short ufwdm, ufwdn, bfwdm, bfwdn;
  17. short tstaleb, tstalen, tstaleu;
  18. int bidok, hidok, hasbid, needbid, holdit;
  19.  
  20. char  *mm[num_mm];
  21. char  wpcall[ln_call];
  22. XBBS  *xbbs;
  23. HOLD  *hold;
  24.  
  25. MAIL_HDR  *mfhs;
  26. MSG_HDR   *tmmhs;
  27.  
  28. FILE *bfl;
  29.  
  30. int mfl, mflb;
  31.  
  32. msgfile(p, n)
  33. char *p;
  34. word n;
  35. {
  36.   sprintf(p, "%s%u", msgdir, n);
  37. }
  38.  
  39. /*
  40.  *  Open file to hold BIDs
  41.  */
  42.  
  43. opnbid()
  44. {
  45.   if ((bfl = fopen(bidfile, "a+")) is NULL) { nofile(bidfile); exit(1); }
  46.   fclose(bfl);
  47. }
  48.  
  49. /*
  50.  *  Write message header.
  51.  */
  52.  
  53. wt_mmhs()
  54. {
  55.   if (port->mmhs->rn) write_rec (mfl, port->mmhs->rn, (char *)port->mmhs);
  56. }
  57.  
  58.  
  59. /*
  60.  *  Get message title.
  61.  */
  62.  
  63. get_title()
  64. {
  65.   while(!getdat());
  66.   remnl(port->line);
  67.   strncpy(port->mmhs->title, port->line, mhtitl);
  68. }
  69.  
  70. /*
  71.  *  Parse the [@ bbs] and [< from] fields of a command.
  72.  */
  73.  
  74. atfrom(i)
  75. int i;
  76. {
  77.   if (*port->fld[i] is '<') pcall(port->mmhs->from, port->fld[i + 1]);
  78.   else if (*port->fld[i] is '@')
  79.   {
  80.     pcall(port->mmhs->bbs, port->fld[i +1]);
  81.     if ((strchr(port->fld[i + 1], '.')) is NULL) return;
  82.     port->mmhs->ext = 2;
  83.     fill (port->mmhs->call, '\0', 125);
  84.     strncpy(port->mmhs->call[0], port->fld[i + 1], 64);
  85.   }
  86. }
  87.  
  88. /*
  89.  *  Parse the fields of a send command.
  90.  */
  91.  
  92. pfld()
  93. {
  94.   hasbid = false;
  95.  
  96.   port->mmhs->type = port->opt2;
  97.   pcall(port->mmhs->to, port->fld[1]);
  98.   strncpy(port->mmhs->from, port->user->call, ln_call);
  99.   fill(port->mmhs->bbs, ' ', ln_call);
  100.   fill(port->mmhs->bid, ' ', ln_bid);
  101.   port->mmhs->ext = 0;
  102.  
  103.   if (port->flds > 3) atfrom(port->flds - 2);
  104.   if (port->flds > 5) atfrom(port->flds - 4);
  105.  
  106.   if (port->flds > 2)
  107.   if(*port->fld[port->flds-1] is '$')
  108.   {
  109.     if (*(port->fld[port->flds - 1] + 1) isnt NULL)
  110.     {
  111.     strncpy(port->mmhs->bid, port->fld[port->flds - 1] + 1, ln_bid);
  112.     hasbid = true;
  113.     }
  114.     if (port->flds > 4) atfrom(port->flds - 3);
  115.     if (port->flds > 6) atfrom(port->flds - 5);
  116.   }
  117.  
  118.   initmsg(true);  
  119.   if(!bidok) {
  120.     if (port->user->options & (u_bbs | u_expert)) outstr("Sj:\n");
  121.     else prtx(mm[0]);
  122.     get_title();
  123.     return;
  124.   }
  125.   else {  
  126.     if (hasbid) {
  127.       checkbid();
  128.       if (!needbid) {
  129.         outstr("No - Already have it\n");
  130.         sprintf(port->mmhs->title, "<<%6.6s - %s>>",
  131.                   port->user->call, port->fld[port->flds-1]);
  132.         wt_mmhs();
  133.         return;
  134.       }
  135.       prtx("OK $C\n");
  136.       get_title();
  137.       return;
  138.     }
  139.     else {
  140.       prtx("OK $C\n");
  141.       get_title();
  142.       needbid = true;     /* will check and may assign one later */
  143.       return;
  144.     }
  145.   }
  146. }
  147.  
  148. /*
  149.  *  Create the header line.
  150.  */
  151.  
  152. makehdr()
  153. {
  154.   register char st;
  155.  
  156.   st = 'N';
  157.   if (port->mmhs->stat & m_stale) st = 'O';
  158.   if (port->mmhs->stat & m_fwd)   st = 'F';
  159.   if (port->mmhs->stat & m_read)  st = 'Y';
  160.   if (port->mmhs->stat & m_hold)  st = 'H';
  161.   if (port->mmhs->stat & m_kill)  st = 'K';
  162.   if (port->mmhs->stat & m_busy)  st = 'B';
  163.   sprintf(tmp->scr,"%5u %c%c %5u %6.6s %6.6s %6.6s %4.4s/%4.4s %s\n",
  164.     port->mmhs->number, port->mmhs->type, st, port->mmhs->size,
  165.     port->mmhs->to, port->mmhs->from, port->mmhs->bbs,
  166.     port->mmhs->date + 2, port->mmhs->time, port->mmhs->title);
  167. }
  168.  
  169. /*
  170.  * Write mail.dat header into text file
  171.  */
  172.  
  173. makehdr2()
  174. {
  175.   register char st, c;
  176.   int msfl;
  177.   char flags[mmesn];
  178.   fill (flags, ' ',mmesn);
  179.   fill (tmp->scr, '\0', 256);
  180.   tmp->scr[254] = '\r'; tmp->scr[255] = '\n';
  181.   if (port->mmhs->ext is 1)
  182.   {
  183.     for (c=0; c < port->mmhs->count; c++)
  184.     flags[c] = port->mmhs->flag[c] + '0';
  185.   }
  186.   st = 'N';
  187.   if (port->mmhs->stat & m_stale) st = 'O';
  188.   if (port->mmhs->stat & m_fwd)   st = 'F';
  189.   if (port->mmhs->stat & m_hold)  st = 'H';
  190.   if (port->mmhs->stat & m_read)  st = 'Y';
  191.   if (port->mmhs->stat & m_kill)  st = 'K';
  192.   sprintf(tmp->scr,
  193.            "%5u %c%c %5u %6.6s %6.6s %6.6s %6.6s %4.4s %-12.12s %5u\r\n",
  194.     port->mmhs->number, port->mmhs->type, st, port->mmhs->size,
  195.     port->mmhs->to, port->mmhs->from, port->mmhs->bbs,
  196.     port->mmhs->date, port->mmhs->time, port->mmhs->bid, port->mmhs->read);
  197.   if (port->mmhs->ext is 2)
  198.        sprintf(tmp->scr+68, "%c %s\r\n%s\r\n", port->mmhs->ext +'0',
  199.        port->mmhs->call, port->mmhs->title);
  200.   else sprintf(tmp->scr+68, "%c %16.16s\r\n%s\r\n", port->mmhs->ext +'0',
  201.        flags, port->mmhs->title);
  202.  
  203.   msgfile(port->cmd, port->mmhs->number);
  204.   if ((msfl = open(port->cmd, O_WRONLY | O_BINARY)) < 0) return;
  205.   write_rec(msfl, 0, (char *)tmp->scr);
  206.   close(msfl);
  207. }
  208.  
  209. /*
  210.  *  Print a message header.
  211.  */
  212.  
  213. prthdr(tit)
  214. int tit;
  215. {
  216.   char *a, *b;
  217.  
  218.   register short i;
  219.   register short docc;
  220.  
  221.   if (tit) prtx(mm[3]);
  222.   makehdr();
  223.   outstr(tmp->scr);
  224.   if((port->opt1 is'L')and((*port->fld[1]isnt';')and(*port->fld[2]isnt';')))
  225.      return;
  226.   if (port->mmhs->ext is 2)
  227.   {
  228.     outstr("    EF:");
  229.     outstr(port->mmhs->call);
  230.     outchar('\n');
  231.   }
  232.   if (port->mmhs->ext is 1) if (port->mode & ops)
  233.   {
  234.     docc = false;
  235.     for (i = 0; i < port->mmhs->count; i++) if (port->mmhs->flag[i])
  236.      docc = true;
  237.  
  238.     if (docc)
  239.     {
  240.       outstr("    cc:");
  241.       for (i = 0; i < port->mmhs->count; i++)
  242.       {
  243.         if (port->mmhs->flag[i]) outchar(' '); else outstr(" *");
  244.         outnb(port->mmhs->call[i], ln_call);
  245.       }
  246.       outchar('\n');
  247.     }
  248.   }
  249.   if (port->mode & ops) if (*port->mmhs->bid isnt ' ')
  250.     {
  251.     outstr("   BID: ");
  252.     a = port->line;
  253.     b = port->mmhs->bid;
  254.     unbl(a, b, ln_bid);
  255.     outstr(port->line);  outchar('\n');
  256.   }
  257. }
  258.  
  259. /*
  260.  *  Read the message, look for the last bbs header.
  261.  *  Set the @ field of the current message to the "at bbs" in that header.
  262.  */
  263.  
  264. findat()
  265. {
  266.   register short i;
  267.  
  268.   fill(port->mmhs->bbs, ' ', ln_call);
  269.   msgfile(port->line, port->mmhs->number);
  270.   if ((port->fl = fopen(port->line, "r")) is NULL) { nofile(port->line); return; }
  271.   fseek(port->fl, (long)RECSIZE, 0);
  272.   while(fgets(port->line, linelen, port->fl) isnt NULL)
  273.   {
  274.     if (!parsehd(port->line)) break;
  275.     pcall(port->mmhs->bbs, orgbbs);
  276.   }
  277.   fclose (port->fl);
  278. }
  279.  
  280. /*
  281.  *  Parse a message header line.
  282.  */
  283.  
  284. parsehd(in)
  285. char *in;
  286. {
  287.   register char *p;
  288.   register int count, n;
  289.  
  290.   if (!ishead(in)) return false;
  291.  
  292.   if ((p = strchr(in, 'R')) is NULL) return false;
  293.   {
  294.     p++;
  295.  
  296.     if (*p is ':') p++;
  297.     if (*p is ' ') p++;
  298.     count = 6;
  299.     n = 0;
  300.     while (*p and count--)
  301.     {
  302.       if (!isalnum(*p)) break;
  303.       orgdate[n++] = *p++;
  304.     }
  305.     orgdate[n] = '\0';
  306.  
  307.     if (*p is '/') p++;
  308.  
  309.     count = 4;
  310.     n = 0;
  311.     while (*p and count--)
  312.     {
  313.       if (!isalnum(*p)) break;
  314.       orgtime[n++] = *p++;
  315.     }
  316.     orgtime[n] = '\0';
  317.   }
  318.  
  319.   if ((p = strchr(in, '@')) is NULL) return false;
  320.   {
  321.     p++;
  322.  
  323. /* skip colon or a space in @:call  OR @ call */
  324.  
  325.     if (*p is ':') p++;
  326.     if (*p is ' ') p++;
  327.     count = ln_call;
  328.     n = 0;
  329.     while (*p and count--)
  330.     {
  331.       if (!isalnum(*p)) break;
  332.       toupper(*p);
  333.       orgbbs[n++] = *p++;
  334.     }
  335.     orgbbs[n] = '\0';
  336.   }
  337.  
  338.   if ((p = strchr(in, '#')) isnt NULL) 
  339.   {
  340.     p++;
  341.  
  342.     if (*p is ':') p++;
  343.     if (*p is ' ') p++;
  344.     count = 5;
  345.     n = 0;
  346.     while (*p and count--)
  347.     {
  348.       if (!isalnum(*p)) break;
  349.       orgmsg[n++] = *p++;
  350.     }
  351.     orgmsg[n] = '\0';
  352.   }
  353.   else
  354.   {
  355.     p = strchr(in, '@');
  356.     p--; count = 5;
  357.     while(count-- and *p isnt ' ') p--;
  358.     p++;
  359.     if (*p is '<') p++;
  360.     count = 5;
  361.     n = 0;
  362.     while (*p and count--)
  363.     {
  364.       if (*p is '@') break;
  365.       orgmsg[n++] = *p++;
  366.     }
  367.     orgmsg[n] = '\0';
  368.   }
  369.   return true;
  370. }
  371.  
  372.  
  373. /*
  374.  *  Find a message given it's number.
  375.  */
  376.  
  377. findmsg(nr)
  378. word nr;
  379. {
  380.   register word i;
  381.  
  382.   for (i = mfhs->last; i; i--)
  383.   {
  384.     read_rec(mfl, i, (char *)port->mmhs);
  385.     if (port->mmhs->number is nr) return true;
  386.     if (port->mmhs->number < nr)  return false;
  387.   }
  388.   return false;
  389. }
  390.  
  391. /*
  392.  *  Create the distribution list, if required.
  393.  */
  394.  
  395. dodis()
  396. {
  397.   register FILE *dfl;
  398.   if (port->mmhs->ext is 2) return;
  399.   port->mmhs->ext = 0;
  400.   if (*port->mmhs->bbs is ' ') return;
  401.  
  402.   unbl(tmp->scr, port->mmhs->bbs, ln_call);
  403.  
  404.   strcpy(port->line, msgdir);
  405.   strcat(port->line, tmp->scr);
  406.   strcat(port->line, ".DIS");
  407.  
  408.   if ((dfl = fopen(port->line, "r")) is NULL) return;
  409.  
  410.   port->mmhs->ext = 1 ;
  411.  
  412.   for (port->mmhs->count = 0;
  413.     (port->mmhs->count < mmesn) and (fgets(tmp->scr, scrmax, dfl) isnt NULL);
  414.     port->mmhs->count++)
  415.   {
  416.     strupr(tmp->scr);
  417.     pcall(port->mmhs->call[port->mmhs->count], tmp->scr);
  418.     if(matchn(port->mmhs->call[port->mmhs->count], port->user->call, ln_call))
  419.          port->mmhs->flag[port->mmhs->count] = false;
  420.     else port->mmhs->flag[port->mmhs->count] = true;
  421.   }
  422.   fclose(dfl);
  423. }
  424.  
  425. /*
  426.  *  Do we hold this message?
  427.  */
  428.  
  429. ishold(c)
  430. char *c;
  431. {
  432.   register HOLD *hp;
  433.  
  434.   for (hp = hold; hp isnt NULL; hp = hp->next)
  435.   if (matchn(hp->call, c, ln_call)) return true;
  436.  
  437.   return false;
  438. }
  439.  
  440. /*
  441.  *  Create message utilities - initmsg and cremsg.
  442.  *  Used by "send message", "make message from file",
  443.  *  "kill msg" (service messages), "copy message".
  444.  */
  445.  
  446. initmsg(h)
  447. int h;
  448. {
  449.   if (s_flag & s_dv) begin_lock();
  450.   read_rec(mfl, 0, (char *)mfhs);
  451.  
  452.   port->mmhs->rn = mfhs->next++;
  453.   port->mmhs->number = mfhs->next_msg++;
  454.   port->mmhs->stat = m_busy;
  455.   strncpy(port->mmhs->date, l_date, ln_date);
  456.   strncpy(port->mmhs->time, l_time, ln_time);
  457.   port->mmhs->read = 0;
  458.   port->mmhs->size = 0;
  459.   if(port->mmhs->ext isnt 2) fill(port->mmhs->call, '\0', 125);
  460.   if(h)sprintf(port->mmhs->title, "<<%6.6s -- disconnected>>",port->user->call);
  461.  
  462.  
  463. /*
  464.  *  Clean up the file header.
  465.  */
  466.  
  467.   if (!mfhs->first) mfhs->first = port->mmhs->rn;
  468.   mfhs->last = port->mmhs->rn;
  469.   mfhs->count++;
  470.   write_rec(mfl, 0, (char *)mfhs);
  471.   wt_mmhs();
  472.   mfhs->next_msg--;
  473.   if (s_flag & s_dv) end_lock();
  474. }
  475.  
  476. cremsg()
  477. {
  478.   char *a, *b;
  479.  
  480.   register short i;
  481.   register XBBS *xp;
  482.   register FILE *out;
  483.  
  484.   port->mmhs->stat   = 0;
  485.   strncpy(port->mmhs->date, l_date, ln_date);
  486.   strncpy(port->mmhs->time, l_time, ln_time);
  487.   port->mmhs->read = 0;
  488.   port->mmhs->size = filesize;
  489.  
  490.   for (xp = xbbs; xp isnt NULL; xp = xp->next)
  491.   if (wcm(xp->from, port->mmhs->bbs))
  492.   {
  493.     strncpy(port->mmhs->bbs, xp->to, ln_call);
  494.     break;
  495.   }
  496.  
  497.   if (ishold(port->mmhs->to))   port->mmhs->stat = m_hold;
  498.   if (ishold(port->mmhs->from)) port->mmhs->stat = m_hold;
  499.   if (ishold(port->mmhs->bbs))  port->mmhs->stat = m_hold;
  500.  
  501.   if (holdit) port->mmhs->stat = m_hold;
  502.  
  503.   if (*port->mmhs->bid isnt ' ') {
  504.     checkbid();
  505.     if (hasbid) if (!holdit) if (needbid) {
  506.       if ((out = fopen(bidfile,"a")) is NULL) {
  507.         port->msg = mcant; return;
  508.       }
  509.  
  510.       a = port->cmd;
  511.       b = port->mmhs->bid;
  512.       unbl(a, b, ln_bid);
  513.  
  514.       sprintf(port->line, "%4.4s%s\n", port->mmhs->date + 2, port->cmd);
  515.       if (s_flag & s_dv) begin_lock();
  516.       fputs(port->line, out);
  517.       if (s_flag & s_dv) end_lock();
  518.       fclose(out);
  519.     }
  520.   }
  521.   dodis();
  522.  
  523.   if ((port->mmhs->ext is 1) and (*port->mmhs->bid is ' '))
  524.   port->mmhs->stat = m_hold;
  525.  
  526.   wt_mmhs();
  527.   makehdr2();
  528.  
  529.   if (*port->fld[port->flds-1] isnt '$') port->fld[port->flds-1] = nullstr;
  530.  
  531.   sprintf(port->line, "%u %-.6s@%-.6s %s %s", port->mmhs->number,
  532.    port->mmhs->to, port->mmhs->bbs, port->fld[port->flds-1], port->mmhs->title);
  533.  
  534.   log('M', port->opt1, port->opt2, port->line);
  535.   mfhs->next_msg++;
  536. }
  537.  
  538. /*
  539.  *  Set up the beacon line.
  540.  */
  541.  
  542. setfwd()
  543. {
  544.   register char *cp, *lp;
  545.   register short i;
  546.  
  547.   bldfwd();
  548.   if (ufwdm > 1)
  549.   {
  550.     strcpy(port->line, "BT Mail for:");
  551.     cp = ufwd;
  552.     lp = port->line + strlen(port->line);
  553.     while ((cp < ufwd + ln_call * ufwdn) and (lp < port->line + btmax))
  554.     {
  555.       *lp++ = ' ';
  556.       for (i = 0; i < ln_call; i++, cp++) if (*cp isnt ' ') *lp++ = *cp;
  557.     }
  558.     *lp++ = '\n';
  559.     *lp = '\0';
  560.     alltnc(port->line);
  561.   }
  562. }
  563.  
  564. /*
  565.  *  General permission check: sysop or TO or FROM.
  566.  */
  567.  
  568. permit()
  569. {
  570.   if (port->mmhs->stat & (m_kill | m_busy)) return false;
  571.   if (matchn(port->user->call, port->mmhs->to,   ln_call)) return true;
  572.   if (matchn(port->user->call, port->mmhs->from, ln_call)) return true;
  573.   return false;
  574. }
  575.  
  576. /*
  577.  *  Return true if user has kill permission for current message.
  578.  */
  579.  
  580. kpermit()
  581. {
  582.   if (port->mmhs->stat & m_kill) return false;
  583.   if (port->mode & ops) return true;
  584.   if (permit()) return true;
  585.   return ((port->mmhs->type is 'T') and (port->opt2 is 'T'));
  586. }
  587.  
  588. /*
  589.  *  Return true if user has list permission for current message.
  590.  */
  591.  
  592. lpermit()
  593. {
  594.   if (port->user->options & u_sysop) return true;
  595.   if (permit()) return true;
  596.   return ((port->mmhs->type isnt 'P')
  597.       and !(port->mmhs->stat & (m_fwd | m_kill | m_busy)));
  598. }
  599.  
  600. /*
  601.  *  Return true if user has read permission for current message.
  602.  */
  603.  
  604. rpermit()
  605. {
  606.   if ( port->mode & ops) return true;
  607.   if (permit()) return true;
  608.   return (port->mmhs->type isnt 'P');
  609. }
  610.  
  611. /*
  612.  *  Clean the mail file.
  613.  *  Force drain of buffers, update of directory item.
  614.  */
  615.  
  616. clnmsg()
  617. {
  618.   close(mfl);
  619.   mfl = open(mbfile, O_RDWR | O_BINARY);
  620. }
  621.  
  622. /*
  623.  *  Close the mail file.
  624.  */
  625.  
  626. clsmsg()
  627. {
  628.   close (mfl);
  629. }
  630.  
  631. /*
  632.  *  Open the mail file.
  633.  */
  634.  
  635. opnmsg()
  636. {
  637.   register char *tp;
  638.  
  639. /*
  640.  *  Allocate space for the mail file records.
  641.  */
  642.  
  643.   mfhs  =  (MAIL_HDR *) malloc(sizeof(MAIL_HDR));
  644.   tmmhs =  (MSG_HDR *)  malloc(sizeof(MSG_HDR));
  645.  
  646. /*
  647.  *  Allocate the "who has mail" lists.
  648.  */
  649.  
  650.   ufwd = (char *) malloc (ln_call * ufwdm);
  651.   bfwd = (char *) malloc (ln_call * bfwdm);
  652.   if (bfwd is NULL) errall();
  653.  
  654. /*
  655.  *  Open the file. If it does not exist, make one.
  656.  */
  657.  
  658.   if ((mfl = open(mbfile, O_RDWR | O_BINARY)) < 0)
  659.   {
  660.     if ((mfl = open(mbfile, O_CREAT | O_RDWR | O_BINARY, pmode)) < 0)
  661.       { nofile(mbfile); exit(1); }
  662.     inithdr();
  663.     mfhs->next_msg = 1;
  664.     write_rec(mfl, 0, (char *)mfhs);
  665.   }
  666.  
  667. /*
  668.  *  Read the mail file header.
  669.  */
  670.  
  671.   read_rec(mfl, 0, (char *)mfhs);
  672.  
  673. /*
  674.  *  If wrong version mail file, quit now.
  675.  */
  676.  
  677.   if (mfhs->version isnt mb_version)
  678.   {
  679.     printf("Expected version %d, got version %d\n",
  680.       mb_version, mfhs->version);
  681.     nofile(mbfile);
  682.     exit(1);
  683.   }
  684.  
  685. }
  686.  
  687. /*
  688.  *  Initialize the mail file header.
  689.  */
  690.  
  691. inithdr()
  692. {
  693.   mfhs->next    = 1;
  694.   mfhs->first   = 0;
  695.   mfhs->last    = 0;
  696.   mfhs->version = mb_version;
  697.   mfhs->free    = 0;
  698.   mfhs->count   = 0;
  699.   mfhs->unt_msg = 1;
  700.  
  701.   curtim();
  702.   strncpy(mfhs->date, l_date, ln_date);
  703.   strncpy(mfhs->time, l_time, ln_time);
  704.   fill(mfhs->unu, '\0', mfhsunu);
  705. }
  706.  
  707. /*
  708.  *  Open mail file and read first record.
  709.  */
  710.  
  711. readmsg()
  712. {
  713.   mfl = open(mbfile, O_RDWR | O_BINARY);
  714.   read_rec(mfl, 0, (char *)mfhs);
  715. }
  716.  
  717. /*
  718.  *  Does this station want us to send BIDs ?
  719.  */
  720.  
  721. isbid()
  722. {
  723.   register char *f;
  724.  
  725. /*  Is this a sid? It must have a '-' and end with a ']'  */
  726.  
  727.   if ((port->line[strlen(port->line) - 2] isnt ']' ) or
  728.      ((f =  strrchr(port->line, '-')) is NULL))
  729.      return;
  730.  
  731. /*  Look for specal characters in the last field.  */
  732.  
  733.   f++;
  734.   for (; *f isnt ']';f++)
  735.   switch(*f)
  736.   {
  737.      case 'H' : hidok = true; break;
  738.      case '$' : if(*(f+1) is ']') bidok = true; break;
  739.   }
  740. }
  741.  
  742. /*
  743.  *  Check to see whether we already have this BID.
  744.  */
  745.  
  746. checkbid()
  747. {
  748.   FILE *out;
  749.   char *a, *b;
  750.  
  751.   if (*port->mmhs->bid is ' ') { needbid = true; return; }
  752.   if ((out = fopen(bidfile, "r")) is NULL) {
  753.     nofile(bidfile); return; 
  754.   }
  755.   while (fgets(port->line, linelen, out) isnt NULL) {
  756.  
  757.     /* the first 4 characters are the date */
  758.  
  759.     strcpy(port->cmd, port->line + 4);
  760.     a = port->cmd;
  761.     remnl(a);
  762.  
  763.     a = port->line;
  764.     b = port->mmhs->bid;
  765.     unbl(a, b, ln_bid);
  766.  
  767.     if (match(port->cmd, port->line)) {
  768.       needbid = false; 
  769.       fclose(out);
  770.       return;
  771.     }
  772.   }
  773.   needbid = true;
  774.   fclose(out);
  775. }
  776.  
  777. /****************************************
  778.  *                                      *
  779.  *  Code for the commands starts here   *
  780.  *                                      *
  781.  ****************************************/
  782.  
  783. /*
  784.  *  GM or GR command: backup the mail file.
  785.  */
  786.  
  787. untmsg()
  788. {
  789.   register word inhdr, me;
  790.   if (port->opt2 isnt 'A') { if (sure()) return; }
  791.   if (!mfhs->count) { port->msg = mm[5]; return; }
  792.   prtx(mm[6]);
  793.  
  794.   close(mfl);         /*  Close current.  */
  795.  
  796.   unlink(mbbfile);    /*  Delete backup   */
  797.  
  798. /*
  799.  *  Copy current to backup.
  800.  */
  801.  
  802.   if (samedir(mbfile, mbbfile)) rename(mbfile, mbbfile);
  803.   else copy(mbfile, mbbfile, false);
  804.  
  805.   unlink(mbfile);     /*  Delete current.  */
  806.  
  807. /*
  808.  *  Open new current and backup.
  809.  */
  810.  
  811.   mfl  = open(mbfile,  O_CREAT  | O_RDWR | O_BINARY, pmode);
  812.   mflb = open(mbbfile, O_RDONLY | O_BINARY);
  813.  
  814.   read_rec(mflb, 0, (char *)mfhs);
  815.   me = mfhs->last;
  816.   inhdr = mfhs->first;
  817.   inithdr();
  818.  
  819.   if (port->opt2 is 'R')
  820.   {
  821.     if (port->flds is 1) mfhs->next_msg = 1;
  822.     else mfhs->next_msg = atoi(port->fld[1]);
  823.   }
  824.  
  825.  
  826.   while(inhdr <= me)        /*  For each message header ... */
  827.   {
  828.     read_rec(mflb, inhdr, (char *)port->mmhs); /* Read the header. */
  829.  
  830. /*
  831.  *  Tell the sysop about this message.
  832.  */
  833.  
  834.     sprintf(port->line, "Hdr %6u Size %6u # %6u Read %6u",
  835.       inhdr, port->mmhs->size, port->mmhs->number, port->mmhs->read);
  836.     outstr(port->line);
  837.  
  838.     inhdr++;
  839.  
  840.     if (!(port->mmhs->stat & ( m_kill | m_busy)))
  841.     {
  842.        outstr("\n");
  843.  
  844. /*
  845.  *  If renumbering messages, renumber this message.
  846.  */
  847.  
  848.        if (port->opt2 is 'R')
  849.        {
  850.          msgfile(port->line, port->mmhs->number);
  851.          msgfile(port->cmd,  mfhs->next_msg);
  852.          rename(port->line, port->cmd);
  853.          port->mmhs->number = mfhs->next_msg++;
  854.        }
  855.  
  856. /*
  857.  *  Write the header.
  858.  */
  859.  
  860.        port->mmhs->rn = ++mfhs->count;
  861.        wt_mmhs();
  862.     }
  863.     else arcmsg();
  864.   }
  865.  
  866.  
  867. /*
  868.  *  Write the file header.
  869.  */
  870.   if (mfhs->count) mfhs->first = 1;
  871.   mfhs->next = mfhs->count + 1;
  872.   mfhs->last = mfhs->count;
  873.   mfhs->unt_msg = mfhs->next_msg;
  874.   write_rec(mfl, 0, (char *)mfhs);
  875.   close(mflb);
  876.   clnmsg();
  877. }
  878.  
  879.  
  880. /*
  881.  *  Print headers of unread messages for this user.
  882.  */
  883.  
  884. newmsg()
  885. {
  886.   if (findfwd(port->user->call, ufwd, ufwdn) or
  887.       findfwd(port->user->call, bfwd, bfwdn))
  888.   {
  889.     prtx(mm[2]);
  890.     port->opt2 = '\0';
  891.     port->flds = 1;
  892.     lstmsg();
  893.   }
  894. }
  895.  
  896. /*
  897.  *  L command, list messages.
  898.  */
  899.  
  900. lstmsg()
  901. {
  902.   register char *p;
  903.   register short done, ok;
  904.   word h, found, more;
  905.  
  906. /*
  907.  *  First set up arguments.
  908.  */
  909.  
  910.   found = 0; more = 0; done = false;
  911.   if ((*port->fld[1] is ';') or (*port->fld[2] is ';')) port->flds--;
  912.   switch(port->opt2)
  913.   {
  914.     case '@' :
  915.     case '<' :
  916.     case '>' : pcall(tcall, port->fld[1]); break;
  917.     case '\0': break;
  918.     case 'E' :
  919.     case ' ' : if (port->flds is 1) more = port->user->msg_number;
  920.     default  : if (port->flds is 2)
  921.       {
  922.         if (!num(port->fld[1])) { port->msg = mwhat; return; }
  923.         more = atoi(port->fld[1]);
  924.       }
  925.   }
  926.  
  927. /*
  928.  *  Log it, unless is initial login check for msgs.
  929.  */
  930.  
  931.   if (port->opt2)
  932.   {
  933.     sprintf(port->line, "%u", more);
  934.     log('M', 'L', port->opt2, port->line);
  935.   }
  936.  
  937. /*
  938.  *  Paw through the messages and show what requested.
  939.  */
  940.  
  941.   for (h = mfhs->last; h and !done; h--)
  942.   {
  943.     read_rec(mfl, h, (char *)port->mmhs);
  944.     if ((port->opt2 is 'L') or ((port->opt2 is 'E') and (port->flds is 2)))
  945.       done = (found is more); else done = (port->mmhs->number < more);
  946.  
  947.     ok = !done;
  948.  
  949. /*
  950.  *  Does this user have read permission for this message?
  951.  */
  952.  
  953.     if (ok) ok = lpermit();
  954.     if (ok) if (port->mmhs->stat & m_kill)
  955.     ok = ((port->opt2 is 'K') or (port->opt2 is 'E'));
  956.     if (ok) if (port->mmhs->stat & m_busy) ok = (port->opt2 is 'E');
  957.  
  958. /*
  959.  *  Is this message wanted?
  960.  */
  961.  
  962.     if (ok) switch(port->opt2)
  963.     {
  964.       case '\0': ok = matchn(port->user->call, port->mmhs->to, ln_call); break;
  965.       case 'E' : break;
  966.       case 'K' : ok = (port->mmhs->stat & m_kill); break;
  967.       case 'F' : ok = (port->mmhs->stat & m_fwd);  break;
  968.       case 'H' : ok = (port->mmhs->stat & m_hold); break;
  969.       case 'L' : break;
  970.       case 'M' : ok = matchn(port->user->call, port->mmhs->to, ln_call);
  971.                 if (!ok) ok = matchn(port->user->call, port->mmhs->from, ln_call);
  972.                 break;
  973.  
  974.       case 'O' : ok = (port->mmhs->stat & m_stale); break;
  975.       case 'U' : ok = !((port->mmhs->type is 'B')or(port->mmhs->type is 'A')
  976.                        or (port->mmhs->stat & (m_fwd | m_read))); break;
  977.       case 'Y' : ok = (port->mmhs->stat & m_read);  break;
  978.       case '@' : ok = matchn(tcall, port->mmhs->bbs, ln_call); break;
  979.       case '<' : ok = matchn(tcall, port->mmhs->from, ln_call); break;
  980.       case '>' : ok = matchn(tcall, port->mmhs->to, ln_call); break;
  981.       default  : ok = ((port->mmhs->type is port->opt2) or
  982.                        (port->opt2 is ' '));
  983.     }
  984.     if (ok) prthdr(!found++);
  985.   }
  986.   if (!found) port->msg = mfind;
  987.   s_flag setbit s_update;
  988. }
  989.  
  990. /*
  991.  *  CM command: duplicate a message.
  992.  */
  993.  
  994. dupmsg()
  995. {
  996.   word tmpsize;
  997.   if (!findmsg(atoi(port->fld[2]))) { port->msg = mnmsg; return; }
  998.   port->opt1 = 'S';
  999.  
  1000.   prthdr(true);
  1001.   pcall(port->mmhs->to, port->fld[1]);
  1002.   fill(port->mmhs->bbs, ' ', ln_call);
  1003.   port->mmhs->ext = 0;
  1004.  
  1005.   if (port->flds > 3) atfrom(port->flds - 2);
  1006.   if (port->flds > 5) atfrom(port->flds - 4);
  1007.   tmpsize = port->mmhs->size;
  1008.  
  1009.   msgfile(port->cmd, port->mmhs->number);
  1010.   initmsg(false);
  1011.   msgfile(port->line, mfhs->next_msg);
  1012.   copy(port->cmd, port->line, false);
  1013.   filesize = tmpsize;
  1014.   cremsg();
  1015. }
  1016.  
  1017. /*
  1018.  *  F command: copy a message to a file.
  1019.  */
  1020.  
  1021. filmsg()
  1022. {
  1023.   register char *p;
  1024.   register short hdr, append;
  1025.   register FILE *out;
  1026.  
  1027.   if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
  1028.  
  1029.   hdr = true;
  1030.   append = false;
  1031.  
  1032.   if (port->flds is 4) for (p = port->fld[3]; *p; p++) switch (*p)
  1033.   {
  1034.     case 'A' : append = true; break;
  1035.     case 'N' : hdr    = false; break;
  1036.     default: ;
  1037.   }
  1038.  
  1039.   if (port->opt2 is ' ') strcpy(port->line, port->fld[2]);
  1040.   else if (getdir(port->fld[2]) is NULL) { port->msg = mndir; return; }
  1041.  
  1042.   if (append) out = fopen (port->line, "a"); else
  1043.   {
  1044.     if ((out = fopen (port->line, "r")) isnt NULL)
  1045.       { fclose(out); port->msg = mexst; return; }
  1046.     out = fopen (port->line, "w");
  1047.   }
  1048.  
  1049.   if (out is NULL) { port->msg = mcant; return; }
  1050.  
  1051.   sprintf(tmp->scr, "%s %s", port->fld[1], port->line);
  1052.   log('M', 'D', port->opt2, tmp->scr);
  1053.  
  1054.   prthdr(true);
  1055.  
  1056.   if (hdr) fputs(tmp->scr, out);
  1057.  
  1058.   msgfile(port->cmd, port->mmhs->number);
  1059.  
  1060.   if ((port->fl = fopen(port->cmd, "r")) is NULL)
  1061.     { fclose(out); nofile(port->cmd); return; }
  1062.   fseek( port->fl, (long)RECSIZE, 0);
  1063.   while (fgets(tmp->scr, scrmax, port->fl) isnt NULL) fputs(tmp->scr, out);
  1064.  
  1065.   fclose(port->fl);
  1066.   fclose(out);
  1067. }
  1068.  
  1069. /*
  1070.  *  Upload the message text file.
  1071.  */
  1072.  
  1073. uloadm(tname)
  1074. char *tname;
  1075. {
  1076.   register char *tp;
  1077.   register PORTS *p;
  1078.   short first;
  1079.  
  1080.   p = port;
  1081.  
  1082.   if ((p->fl = fopen(tname, "w")) is NULL) { p->msg = mcant; return false; }
  1083.   fseek( p->fl, (long)RECSIZE, 0);
  1084.  
  1085.   first = true;
  1086.   filesize = 0;
  1087.   while (true)
  1088.   {
  1089.     while(!getdat());
  1090.  
  1091. /*
  1092.  *  If user disconnected, timed out, or forced off, zap the file.
  1093.  */
  1094.  
  1095.     if (p->mode & gone)
  1096.     {
  1097.       fclose(p->fl);
  1098.       return false;
  1099.     }
  1100.  
  1101. /*
  1102.  *  If the first line is not a header (thus it is a human entering
  1103.  *  the message), make sure there is an initial blank line before
  1104.  *  the body of the message.
  1105.  */
  1106.  
  1107.     if (first)
  1108.     {
  1109.       first = false;
  1110.       if (!ishead(p->line)) if (*p->line isnt '\n') fputs("\n", p->fl);
  1111.     }
  1112.  
  1113. /*
  1114.  *  Stuff the line into the file.
  1115.  */
  1116.  
  1117.     if (match(p->line, "/EX\n") or match(p->line,"/ex\n"))
  1118.     {
  1119.       fclose(p->fl);
  1120.       return true;
  1121.     }
  1122.  
  1123.  
  1124.     if ((tp = strchr(p->line, cpmeof)) is NULL)
  1125.     {
  1126.       filesize += strlen(p->line);
  1127.       fputs(p->line, p->fl);
  1128.     }
  1129.     else
  1130.     {
  1131.       if (tp isnt p->line)
  1132.       {
  1133.         *tp++ = '\n';
  1134.         *tp   = '\0';
  1135.         filesize += strlen(p->line);
  1136.         fputs(p->line, p->fl);
  1137.       }
  1138.       fclose(p->fl);
  1139.       return true;
  1140.     }
  1141.   }
  1142. }
  1143.  
  1144. /*
  1145.  *  "Display the message text" utility.
  1146.  */
  1147.  
  1148. dloadm(sh)
  1149. short sh;
  1150. {
  1151.   short first;
  1152.  
  1153.   sprintf(port->line, "%u", port->mmhs->number);
  1154.   log('M', 'R', port->opt2, port->line);
  1155.   port->mmhs->read++;
  1156.   if (matchn(port->user->call, port->mmhs->to, ln_call))
  1157.     port->mmhs->stat setbit m_read;
  1158.   wt_mmhs();
  1159.   makehdr2();
  1160.   prthdr(true);
  1161.  
  1162.   msgfile(port->line, port->mmhs->number);
  1163.  
  1164.   if ((port->fl = fopen(port->line, "r")) is NULL)
  1165.     { nofile(port->line); return; }
  1166.  
  1167.   fseek( port->fl, (long)RECSIZE, 0 );
  1168.   pgst(NULL);
  1169.   pgck();   /* First line of header */
  1170.   pgck();   /* Second line of header */
  1171.   pgck();   /* Path line */
  1172.   if (port->mmhs->ext) pgck();
  1173.   if (*port->mmhs->bid isnt ' ') pgck();
  1174.  
  1175.   strcpy(tmp->scr, "  Path: ");
  1176.   first = true;
  1177.  
  1178.   while(fgets(port->line, linelen, port->fl) isnt NULL)
  1179.   {
  1180.     if (!sh)
  1181.     {
  1182.       sh = !parsehd(port->line);
  1183.       if (sh)
  1184.       {
  1185.         if (!first)
  1186.         {
  1187.           strcat(tmp->scr, "\n\n");
  1188.           outstr(tmp->scr);
  1189.           pgck();
  1190.           prtx("Date: $j/$k\n");  pgck();
  1191.           prtx("From: $P @ $a\n");  pgck();
  1192.           prtx("Message-Id: <$m@$a>\n");  pgck();
  1193.           prtx("To: $G @ ");
  1194.           if (*port->mmhs->bbs is ' ')  prtx("$O\n");
  1195.           else if (port->mmhs->ext is 2) prtx("$h\n");
  1196.           else prtx("$A\n");  pgck();
  1197.           prtx("Subject: $E\n\n");  pgck();
  1198.         }
  1199.       }
  1200.       else
  1201.       {
  1202.         if (!first) strcat(tmp->scr, "!");
  1203.         strcat(tmp->scr, orgbbs);   
  1204.         first = false;
  1205.       }
  1206.     }
  1207.  
  1208.     if (sh)
  1209.     {
  1210.       outstr(port->line);
  1211.       if ((pgck() is 'Q') or (chkdis())) { fclose(port->fl); return; }
  1212.     }
  1213.   }
  1214.   fclose (port->fl);
  1215. }
  1216.  
  1217. /*
  1218.  *  RM command: read my messages.
  1219.  */
  1220.  
  1221. rdmsgm()
  1222. {
  1223.   register short found;
  1224.   register word h;
  1225.  
  1226.   found = false;
  1227.   for (h = mfhs->first; h and h <= mfhs->last; h++)
  1228.   {
  1229.     read_rec(mfl, h, (char *)port->mmhs);
  1230.     if (!(port->mmhs->stat & (m_read | m_fwd | m_hold | m_busy)) and
  1231.       matchn(port->user->call, port->mmhs->to, ln_call))
  1232.     {
  1233.       dloadm(false);
  1234.       found = true;
  1235.       if (pause() is 'Q') return;
  1236.     }
  1237.   }
  1238.   if (!found) port->msg = mfind;
  1239. }
  1240.  
  1241. /*
  1242.  *  R command: read one message.
  1243.  */
  1244.  
  1245. rdmsg()
  1246. {
  1247.   if (!num(port->fld[1]))           { port->msg = mwhat; return; }
  1248.   if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
  1249.   if (!rpermit())                   { port->msg = mprot; return; }
  1250.  
  1251.   dloadm(port->opt2 is 'H');
  1252. }
  1253.  
  1254. /*
  1255.  *  KF, KM, KO, KY, KK commands, kill multiple messages.
  1256.  */
  1257.  
  1258. klmsgm()
  1259. {
  1260.   register short ok;
  1261.   register short found;
  1262.   word h, next;
  1263.  
  1264.   if (port->flds is 2) pcall(tcall, port->fld[1]);
  1265.  
  1266.   found = false;
  1267.   for (h = mfhs->first; h and h <= mfhs->last; h++)
  1268.   {
  1269.     read_rec(mfl, h, (char *)port->mmhs);
  1270.  
  1271.     ok = kpermit();
  1272.     if (ok) ok = !(port->mmhs->stat & m_hold);
  1273.  
  1274.     if (ok) if (port->flds is 2) ok = matchn(tcall, port->mmhs->to, ln_call);
  1275.  
  1276.     if (ok) switch(port->opt2)
  1277.     {
  1278.       case 'F' : ok = (port->mmhs->stat & m_fwd); break;
  1279.       case 'M' :
  1280.         ok = ((port->mmhs->stat & m_read) and
  1281.           matchn(port->user->call, port->mmhs->to, ln_call));
  1282.         break;
  1283.       case 'O' : ok = (port->mmhs->stat & m_stale); break;
  1284.       case 'Y' : ok = (port->mmhs->stat & m_read);  break;
  1285.     }
  1286.  
  1287.     if (ok)
  1288.     {
  1289.       sprintf(port->line, "%u", port->mmhs->number);
  1290.       log('M', 'K', port->opt2, port->line);
  1291.       prtx(mm[7]);
  1292.       found = true;
  1293.       port->mmhs->stat setbit m_kill;
  1294.       write_rec(mfl, port->mmhs->rn, (char *)port->mmhs);
  1295.       makehdr2();
  1296.     }
  1297.   }
  1298.   if (!found) port->msg = mfind;
  1299. }
  1300.  
  1301. /*
  1302.  *  K command, kill a message.
  1303.  */
  1304.  
  1305. klmsg()
  1306. {
  1307.   register short dosvc;
  1308.  
  1309.   if (!num(port->fld[1]))           { port->msg = mwhat; return; }
  1310.   if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
  1311.   if (port->mmhs->stat & m_kill)    { port->msg = mnmsg; return; }
  1312.   if (!kpermit())                   { port->msg = mprot; return; }
  1313.  
  1314.   log('M', 'K', port->opt2, port->fld[1]);
  1315.  
  1316.   dosvc = (port->opt2 is 'T') and
  1317.           (port->mmhs->type is 'T') and
  1318.           (s_param & s_svc);
  1319.  
  1320.   if (dosvc) findat();
  1321.  
  1322. /*
  1323.  *  Marked the message as  Killed.
  1324.  */
  1325.  
  1326.   port->mmhs->stat setbit m_kill;
  1327.   write_rec(mfl, port->mmhs->rn, (char *)port->mmhs);
  1328.   makehdr2();
  1329.  
  1330. /*
  1331.  *  If this is KT of T type message, and we do service messages,
  1332.  *  do the service message.
  1333.  */
  1334.  
  1335.   if (dosvc)
  1336.   {
  1337.     port->opt1 = 'S';
  1338.     strncpy(port->mmhs->to, port->mmhs->from, ln_call);
  1339.     strncpy(port->mmhs->from, cport->user->call, ln_call);
  1340.     port->mmhs->type = 'S';
  1341.     fill(port->mmhs->bid, ' ', ln_bid);
  1342.     port->mmhs->ext = 0;
  1343.     initmsg(false);
  1344.     msgfile(port->line, mfhs->next_msg);
  1345.     port->fl = fopen(port->line, "w");
  1346.     fseek(port->fl, (long)RECSIZE, 0);
  1347.     fprintf(port->fl, "Msg %5u taken from %6.6s by %6.6s at %4.4s on %6.6s\n",
  1348.       port->mmhs->number, cport->user->call, port->user->call, l_time, l_date);
  1349.     fclose(port->fl);
  1350.  
  1351.     filesize = 56;
  1352.     cremsg();
  1353.   }
  1354.   port->msg = mdone;
  1355. }
  1356.  
  1357. /*
  1358.  *  S command: send a message.
  1359.  */
  1360.  
  1361. sndmsg()
  1362. {
  1363.   FILE *out;
  1364.   char *a, *b;
  1365.  
  1366.   holdit = false;   /* initialize it to something */
  1367.  
  1368.   pfld();
  1369.   if (port->mode & gone) return;
  1370.  
  1371.   if (bidok) {
  1372.     if (!needbid) return;
  1373.   }
  1374.   else {
  1375.     if (port->user->options & (u_bbs | u_expert)) outstr("Msg:\n");
  1376.     else prtx(mm[1]);
  1377.   }
  1378.  
  1379.   msgfile(port->cmd, mfhs->next_msg);
  1380.   if (!uloadm(port->cmd)) return;
  1381.  
  1382. /*
  1383.  *  If this is a Bulletin and has no BID, 
  1384.  *  parse the headers and give it one.
  1385.  */
  1386.   if (!hasbid)
  1387.   if (!iscall(port->mmhs->to))
  1388.   if (port->mmhs->type is 'B')
  1389.   {
  1390.         msgfile(port->cmd, mfhs->next_msg);
  1391.         a = port->line;
  1392.         b = cport->user->call;
  1393.         unbl(a, b, 6);
  1394.  
  1395. /* Default the BID as to coming from this BBS with our msg number. */
  1396.  
  1397.         sprintf(tmp->scr, "%-u_%-s", mfhs->next_msg, port->line);
  1398.  
  1399. /* Now parse the headers if it came from another BBS. */
  1400.  
  1401.         if ((out = fopen(port->cmd, "r")) is NULL)
  1402.         {
  1403.            nofile(port->cmd); return;
  1404.         }
  1405.         fseek(out, (long)RECSIZE, 0);
  1406.         while (fgets(port->line, linelen, out) isnt NULL)
  1407.         {
  1408.            if (parsehd(port->line))
  1409.            {
  1410.              sprintf(tmp->scr, "%s_%s", orgmsg, orgbbs);
  1411.            }
  1412.         }
  1413.         fclose(out);
  1414.         strncpy(port->mmhs->bid, tmp->scr, ln_bid);
  1415.         hasbid = true;
  1416.   }
  1417.   checkbid(); 
  1418.   if (!needbid) holdit = true;
  1419.   else holdit = false;
  1420.   
  1421.   /*  If a message is to an individual, 
  1422.    *  automatically make it a private message.
  1423.    */
  1424.  
  1425.   if (port->opt2 is ' ')
  1426.   if (iscall(port->mmhs->to)) port->mmhs->type = 'P';
  1427.  
  1428.   cremsg();
  1429. }
  1430.  
  1431. /*
  1432.  *  SM command, send a message to a distribution list.
  1433.  */
  1434.  
  1435. sndmlt()
  1436. {
  1437.   register FILE *fl;
  1438.   char fn[80];
  1439.   register short first = true;
  1440.   word tmpsize;
  1441.   
  1442.   holdit = false;
  1443.   fill(port->mmhs->bid, ' ', ln_bid);
  1444.  
  1445.   if ((fl = fopen(port->fld[1], "r")) is NULL)
  1446.     { nofile(port->fld[1]); return; }
  1447.  
  1448.   prtx(mm[0]);
  1449.   get_title();
  1450.   if (port->mode & gone) { fclose(fl); return; }
  1451.  
  1452.   if (port->flds is 3) if (*port->fld[port->flds-1] is '$')
  1453.   {
  1454.     if (*(port->fld[port->flds-1] + 1) isnt NULL)
  1455.     {
  1456.       strncpy(port->mmhs->bid, port->fld[port->flds-1] + 1, ln_bid);
  1457.       hasbid = true;
  1458.     }
  1459.   }
  1460.  
  1461.   prtx(mm[1]);
  1462.  
  1463.   strncpy(port->mmhs->from, port->user->call, ln_call);
  1464.   port->mmhs->ext = 0;
  1465.   initmsg(false);
  1466.   msgfile(fn, mfhs->next_msg);
  1467.   if (!uloadm(fn)) { fclose(fl); return; }
  1468.   tmpsize = filesize;
  1469.  
  1470.   while (fgets(port->line, linelen, fl) isnt NULL)
  1471.   {
  1472.     parse();
  1473.     if (!first)
  1474.     {
  1475.       port->mmhs->ext = 0;
  1476.       initmsg(false);
  1477.       msgfile(port->line, mfhs->next_msg);
  1478.       copy(fn, port->line, false);
  1479.     }
  1480.     port->mmhs->type = port->opt2;
  1481.     pcall(port->mmhs->to, port->fld[1]);
  1482.     fill(port->mmhs->bbs, ' ', ln_call);
  1483.  
  1484.     if(port->flds > 3) atfrom(2);
  1485.     if(port->flds > 5) atfrom(4);
  1486.     filesize = tmpsize;
  1487.     cremsg();
  1488.     first = false;
  1489.   }
  1490.   fclose(fl);
  1491. }
  1492.  
  1493. /*
  1494.  *  M command, make a message from a file.
  1495.  */
  1496.  
  1497. makmsg()
  1498. {
  1499.   if ((port->fl = fopen(port->fld[2], "r")) is NULL)
  1500.     { nofile(port->fld[2]); return; }
  1501.   fclose(port->fl);
  1502.   pfld();
  1503.   if (port->mode & gone) return;
  1504.   msgfile(port->line, mfhs->next_msg);
  1505.   copy(port->fld[2], port->line, true);
  1506.   cremsg();
  1507. }
  1508.  
  1509. /*
  1510.  *  MM command, make multiple messages from a file.
  1511.  */
  1512.  
  1513. makmlt()
  1514. {
  1515.   register FILE *dfl;
  1516.   char tnm[80];
  1517.  
  1518.   holdit = false;
  1519.   fill(port->mmhs->bid, ' ', ln_bid);
  1520.  
  1521.   if ((port->fl = fopen(port->fld[2], "r")) is NULL)
  1522.     { nofile(port->fld[2]); return; }
  1523.   fclose(port->fl);
  1524.  
  1525.   if ((dfl = fopen(port->fld[1], "r")) is NULL)
  1526.     { nofile(port->fld[1]); return; }
  1527.  
  1528.   strcpy(tnm, port->fld[2]);
  1529.  
  1530.   if (port->flds is 4) if (*port->fld[port->flds-1] is '$')
  1531.   {
  1532.     if (*(port->fld[port->flds - 1] + 1) isnt NULL)
  1533.     {
  1534.       strncpy(port->mmhs->bid, port->fld[port->flds-1] + 1, ln_bid);
  1535.       hasbid = true;
  1536.     }
  1537.   }
  1538.  
  1539.   prtx(mm[0]);
  1540.   get_title();
  1541.   if (port->mode & gone) { fclose(dfl); return; }
  1542.  
  1543.   while (fgets(port->line, linelen, dfl) isnt NULL)
  1544.   {
  1545.     parse();
  1546.     port->mmhs->type = port->opt2;
  1547.     pcall(port->mmhs->to, port->fld[1]);
  1548.     strncpy(port->mmhs->from, port->user->call, ln_call);
  1549.     fill(port->mmhs->bbs, ' ', ln_call);
  1550.     port->mmhs->ext = 0;
  1551.  
  1552.     if (port->flds > 3) atfrom(2);
  1553.     if (port->flds > 5) atfrom(4);
  1554.     initmsg(false);
  1555.     msgfile(port->line, mfhs->next_msg);
  1556.     copy(tnm, port->line, true);
  1557.     cremsg();
  1558.   }
  1559.   fclose(dfl);
  1560. }
  1561.  
  1562. /*
  1563.  *  Mark stale messages.
  1564.  */
  1565.  
  1566. stale()
  1567. {
  1568.   register word i;
  1569.   register int ts;
  1570.  
  1571.   for (i = mfhs->first; i and i <= mfhs->last; i++)
  1572.   {
  1573.     read_rec(mfl, i, (char *)port->mmhs);
  1574.  
  1575.     ts = tstaleb;
  1576.     if (port->mmhs->type is 'T') ts = tstalen;
  1577.     else if (iscall(port->mmhs->to)) ts = tstaleu;
  1578.  
  1579.     if (!(port->mmhs->stat & m_stale))
  1580.     if (ddiff(port->mmhs->date, l_date) > ts)
  1581.     {
  1582.       port->mmhs->stat setbit m_stale;
  1583.       write_rec(mfl, i, (char *)port->mmhs);
  1584.     }
  1585.   }
  1586. }
  1587.  
  1588. /*
  1589.  *  DW command: make wp message from user file.
  1590.  */
  1591.  
  1592. dwuser()
  1593. {
  1594.   register int i;
  1595.   register short first = true;
  1596.   short doall;
  1597.  
  1598.   if (*wpcall is ' ') return;
  1599.  
  1600.   doall = port->flds is 2;
  1601.   port->opt1 = 'S';
  1602.   filesize = 0;
  1603.  
  1604.   for (i = 1; i <= ufhs->count; i++)
  1605.   {
  1606.     read_rec(ufl, i, (char *)tuser);
  1607.     if ((tuser->state & u_home) and (tuser->state & u_zip))
  1608.     if (doall or !(tuser->state & u_sent))
  1609.     {
  1610.       if (first)
  1611.       {
  1612.         first = false;
  1613.         port->mmhs->type = 'P';
  1614.         strncpy(port->mmhs->to, "WP    ", ln_call);
  1615.         strncpy(port->mmhs->from, cport->user->call, ln_call);
  1616.         strncpy(port->mmhs->bbs, wpcall, ln_call);
  1617.         strcpy(port->mmhs->title, "WP Update");
  1618.         fill(port->mmhs->bid, ' ', ln_bid);
  1619.         port->mmhs->ext = 0;
  1620.         initmsg(false);
  1621.         msgfile(port->line, mfhs->next_msg);
  1622.         port->fl = fopen(port->line, "w");
  1623.       }
  1624.  
  1625.       filesize += 29;
  1626.       fseek(port->fl, (long)RECSIZE, 0);
  1627.       fprintf(port->fl, "%6.6s qth %6.6s zip %6.6s\n",
  1628.           tuser->call, tuser->home_bbs, tuser->zip);
  1629.       tuser->state setbit u_sent;
  1630.       write_rec(ufl, i, (char *)tuser);
  1631.       if (i is port->user->rn) port->user->state setbit u_sent;
  1632.     }
  1633.   }
  1634.  
  1635.   if (!first)
  1636.   {
  1637.     fclose(port->fl);
  1638.     cremsg();
  1639.   }
  1640. }
  1641.  
  1642. /*
  1643.  *  E command, edit a message header.
  1644.  */
  1645.  
  1646. edmsg()
  1647. {
  1648.   FILE *out;
  1649.   char *a, *b;
  1650.  
  1651.   if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
  1652.   while (*port->fld[0] isnt '\0')
  1653.   {
  1654.     prthdr();
  1655.     outstr("t(Y)pe, (S)tatus, (T)o, (F)rom, (B)bs, t(I)tle, bi(D)\n");
  1656.     getcmd();
  1657.     if (port->mode & gone) return;
  1658.     switch (*port->fld[0])
  1659.     {
  1660.       case 'T' : pcall(port->mmhs->to, port->fld[1]); break;
  1661.       case 'F' : pcall(port->mmhs->from, port->fld[1]); break;
  1662.       case 'B' : edbbs(1); break;
  1663.       case 'I' : if (*port->fld[1])
  1664.                  {
  1665.                    remnl(port->line);
  1666.                    strncpy(port->mmhs->title, port->line+2, mhtitl);
  1667.                  }
  1668.                  else *port->mmhs->title = '\0';
  1669.                  break;
  1670.       case 'S' : switch(*port->fld[1])
  1671.                  {
  1672.                    case 'F' : port->mmhs->stat = m_fwd;   break;
  1673.                    case 'H' : port->mmhs->stat = m_hold;  break;
  1674.                    case 'N' : port->mmhs->stat = 0;       break;
  1675.                    case 'O' : port->mmhs->stat = m_stale; break;
  1676.                    case 'Y' : port->mmhs->stat = m_read;  break;
  1677.                  }
  1678.                  break;
  1679.       case 'Y' : if(*port->fld[1]) port->mmhs->type = *port->fld[1];
  1680.                  else port->mmhs->type = ' '; break;
  1681.  
  1682.       case 'D' : if(*port->fld[1]) strncpy(port->mmhs->bid, port->fld[1], ln_bid);
  1683.                  else fill(port->mmhs->bid, ' ', ln_bid);
  1684.                  break;
  1685.     }
  1686.   }
  1687.   wt_mmhs();
  1688.   makehdr2();
  1689.   if (*port->mmhs->bid isnt ' ')
  1690.   {
  1691.     checkbid();
  1692.     if  (needbid)
  1693.     {
  1694.       if ((out = fopen(bidfile,"a")) is NULL)
  1695.       {
  1696.         port->msg = mcant; return; 
  1697.       }
  1698.  
  1699.       a = port->cmd;
  1700.       b = port->mmhs->bid;
  1701.       unbl(a, b, ln_bid);      
  1702.  
  1703.       sprintf(port->line, "%4.4s%s\n", port->mmhs->date + 2, port->cmd);
  1704.       if (s_flag & s_dv) begin_lock();
  1705.       fputs(port->line, out);
  1706.       if (s_flag & s_dv) end_lock();
  1707.       fclose(out);
  1708.     }
  1709.   }
  1710. }
  1711.  
  1712. /*
  1713.  *  ET command, edit an NTS traffic message header.
  1714.  */
  1715.  
  1716. edtfc()
  1717. {
  1718.   register short ok;
  1719.  
  1720.   if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
  1721.   prthdr();
  1722.  
  1723.   ok = (port->mmhs->type is 'T');
  1724.   if (!ok) ok = ((port->mmhs->type is ' ') and matchn(port->mmhs->to, "NTS", 3));
  1725.   if (!ok) { port->msg = mm[12]; return; }
  1726.  
  1727.   prtx(mm[8]);
  1728.   getcmd();
  1729.   if (port->mode & gone) return;
  1730.   if (port->flds) pcall(port->mmhs->to, port->fld[0]);
  1731.  
  1732.   prtx(mm[9]);
  1733.   getcmd();
  1734.   if (port->mode & gone) return;
  1735.   edbbs(0);
  1736.  
  1737.   prtx(mm[10]);
  1738.   getcmd();
  1739.   if (port->mode & gone) return;
  1740.   if (port->flds)
  1741.   {
  1742.     remnl(port->line);
  1743.     strncpy(port->mmhs->title, port->line, mhtitl);
  1744.   }
  1745.   else if (*port->line is ' ') *port->mmhs->title = '\0';
  1746.  
  1747.   prtx(mm[11]);
  1748.   getcmd();
  1749.   if (port->mode & gone) return;
  1750.   if (port->flds) port->mmhs->type = *port->fld[0];
  1751.   else if (*port->line is ' ') port->mmhs->type = ' ';
  1752.  
  1753.   port->mmhs->stat = 0;
  1754.   prthdr();
  1755.   wt_mmhs();
  1756.   makehdr2();
  1757.   sprintf(port->line, "%u %-.6s %s",
  1758.     port->mmhs->number, port->mmhs->to, port->mmhs->title);
  1759.   log('M', 'E', port->opt2, port->line);
  1760. }
  1761.  
  1762. edbbs(f)
  1763. int f;
  1764. {
  1765.   fill(port->mmhs->call, '\0', 125);
  1766.   port->mmhs->ext = 0;
  1767.   fill(port->mmhs->bbs, ' ', ln_call);
  1768.   if(*port->fld[f])
  1769.   {
  1770.     pcall(port->mmhs->bbs, port->fld[f]);
  1771.     if (strchr(port->fld[f], '.') is NULL) dodis();
  1772.     else
  1773.     {
  1774.       port->mmhs->ext = 2;
  1775.       strncpy(port->mmhs->call[0], port->fld[f], 64);
  1776.     }
  1777.   }
  1778. }
  1779.  
  1780.